#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string>
#include <memory>
#include <string.h>
#include <signal.h>
#include "threadPool/threadPool.hpp"

class TCPServer
{
public:
    TCPServer(uint16_t port, std::string ip = "")
        : _ip(ip), _port(port), _tp(new ThreadPool<Task>())
    {
    }

    void Init() // 初始化
    {
        // 1. 创建套接字
        _listen_sock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listen_sock < 0)
        {
            std::cout << ">>>socket error<<<" << std::endl;
            exit(1);
        }
        // 2. 绑定端口
        struct sockaddr_in ser_addr;
        memset(&ser_addr, 0, sizeof ser_addr);
        ser_addr.sin_family = AF_INET;
        ser_addr.sin_addr.s_addr = _ip.empty() ? INADDR_ANY : inet_addr(_ip.c_str());
        ser_addr.sin_port = htons(_port);

        if (bind(_listen_sock, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) < 0)
        {
            std::cout << ">>>bind error<<<" << std::endl;
            exit(1);
        }

        // 3. 监听
        int g_back = 20;
        if (listen(_listen_sock, g_back) < 0)
        {
            std::cout << ">>>listen error<<<" << std::endl;
            exit(1);
        }

        std::cout << ">>>Init Success<<<" << std::endl;
    }

    void Start()
    {
        std::cout << ">>>Ser Running<<<" << std::endl;

        // 4. 连接
        struct sockaddr_in cli_addr;
        _tp->run();

        while (true)
        {
            socklen_t len = sizeof(cli_addr);
            memset(&cli_addr, 0, len);

            _sockId = accept(_listen_sock, (struct sockaddr *)&cli_addr, &len);
            if (_sockId < 0)
            {
                std::cout << ">>>accept error<<<" << std::endl;
                continue;
            }

            // 子进程版
            // signal(SIGCHLD, SIG_IGN); // 忽略子进程退出信号
            // int id = fork();
            // if (id == 0)
            // {
            //     std::cout << ">>>accept Success<<<" << std::endl;

            //     close(_listen_sock);
            //     service(_sockId);
            //     close(_sockId);
            //     exit(1);
            // }
            // close(_sockId);

            // 线程池版
            std::cout << ">>>accept Success<<<" << std::endl;
            Task t(_sockId, service);
            _tp->push(t);
        }
    }

    static void service(int sockid)
    {
        while (true)
        {
            char buffer[1024];
            size_t s = read(sockid, buffer, sizeof(buffer) - 1);
            if (s > 0)
            {
                buffer[s] = 0;
                std::cout << "Get:" << buffer << std::endl;
                int i = 0;
                while (buffer[i] != '\0')
                {
                    buffer[i] = toupper(buffer[i]);
                    ++i;
                }
                std::cout << "Send:" << buffer << std::endl;
                write(sockid, buffer, strlen(buffer));
            }
            else if (s == 0)
            {
                std::cout << ">>>client closed<<<" << std::endl;
                break;
            }
            else
            {
                std::cout << ">>>read error<<<" << std::endl;
                break;
            }
        }
        close(sockid);
    }

    ~TCPServer()
    {
        close(_listen_sock);
        delete _tp;
    }

private:
    std::string _ip;
    uint16_t _port;
    int _listen_sock;
    int _sockId;
    ThreadPool<Task> *_tp;
};